package com.xuecheng.content.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.dto.CourseTeacherDTO;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.api.system.model.dto.CourseCategoryDTO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.enums.content.CourseGradeEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.JsonUtil;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.agent.SystemApiAgent;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.convert.CoursePubConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.entity.CoursePub;
import com.xuecheng.content.entity.CourseTeacher;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {
    /*
     * 业务操作非本数据库的数据，需要注入的是其他service层的代码
     *    service为项目的维度（业务为维度）
     * */
    @Autowired
    private CourseMarketService courseMarketService;

    @Autowired
    private CourseTeacherService courseTeacherService;

    @Autowired
    private TeachplanService teachplanService;

    @Autowired
    private SystemApiAgent systemApiAgent;

    @Autowired
    private CoursePubService coursePubService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * @param params 分页查询参数
     * @param model  条件查询参数
     * @return PageVO 返回结果查询对象
     */
    public PageVO<CourseBaseDTO> queryCourseBaseList(PageRequestParams params, QueryCourseModel model, Long companyId) {
        //1.分页查询设置
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        Page<CourseBase> page = new Page<>(params.getPageNo(), params.getPageSize());
        //2.条件查询设置
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        //3.判断是否搜索课程名称
        if (StringUtil.isNotBlank(model.getCourseName())) {
            queryWrapper.like(CourseBase::getName, model.getCourseName());
        }
        //4.判断是否筛选状态
        if (StringUtil.isNotBlank(model.getAuditStatus())) {
            queryWrapper.eq(CourseBase::getAuditStatus, model.getAuditStatus());
        }

        //5.判断课程状态是否删除
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        /*设置数据隔离*/
        if (!ObjectUtils.isEmpty(companyId)) {
            queryWrapper.eq(CourseBase::getCompanyId, companyId);
        }
        //查询结果
        Page<CourseBase> pageResult = this.page(page, queryWrapper);
        //获取结果集
        List<CourseBase> courseBaseList = pageResult.getRecords();
        //转换为DTO对象
        List<CourseBaseDTO> dtoList = CourseBaseConvert.INSTANCE.entitys2dtos(courseBaseList);
        //将数据设置到VO中,并返回
        PageVO<CourseBaseDTO> pageVO = new PageVO<>(dtoList, pageResult.getTotal(), params.getPageNo(), params.getPageSize());

        return pageVO;
    }

    /**
     * 添加课程基本信息
     *
     * @param courseBaseDTO
     * @return 操作的结果
     */
    @Override
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO courseBaseDTO) {
        //1.对关键数据的判断
        verifyCourseMsg(courseBaseDTO);
        //2.进行新增操作
        //将dto转为po存储到数据库中
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(courseBaseDTO);
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        boolean courseBaseResult = this.save(courseBase);
        if (!courseBaseResult) {
            throw new RuntimeException("添加课程失败");
        }
        //3.保存课程营销数据
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(courseBaseDTO.getCharge());
        //如果是收费课程,就设置价格
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(courseBaseDTO.getCharge())) {
            courseMarket.setPrice(courseBaseDTO.getPrice().floatValue());
        }
        boolean courseMarketResult = this.courseMarketService.save(courseMarket);
        if (!courseMarketResult) {
            throw new RuntimeException("保存课程营销信息失败");
        }
        //4.获取数据
        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        resultDTO.setCharge(courseBaseDTO.getCharge());
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(courseMarket.getCharge().toString())) {
            resultDTO.setPrice(BigDecimal.valueOf(courseMarket.getPrice()));
        }

        return resultDTO;
    }


    /**
     * 根据Id查询课程基础信息
     *
     * @param courseBaseId 课程的Id值
     * @param companyId    公司的Id值
     * @return CourseBaseDTO
     */
    /*
     * 1.判断关键的数据
     *   课程id
     *   公司id
     * 2.根据课程id查询课程基础信息
     *   判断根据id获得课程基础信息是否存在
     *   将课程基础信息中的公司id和传入的公司id进行对比
     * 3.封装DTO数据
     *   1.课程基础信息
     *   2.课程营销
     * */
    @Override
    public CourseBaseDTO getById(Long courseBaseId, Long companyId) {
        //1.判断关键数据
        if (!ObjectUtil.isAllNotEmpty()) {
            throw new RuntimeException("关键数据不匹配");
        }
        CourseBase courseBase = this.getById(courseBaseId);
        //2.判断是否是一家公司
        verifyPO(companyId, courseBase);
        //3.根据课程id查询课程营销数据
        LambdaQueryWrapper<CourseMarket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseMarket::getCourseId, courseBaseId);

        CourseMarket courseMarket = courseMarketService.getOne(queryWrapper);

        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("课程营销数据不存在");
        }
        //4.将po转为dto数据并返回
        CourseBaseDTO dtoResult = CourseBaseConvert.INSTANCE.entity2dto(courseBase);

        // 如果课程为收费课程需要赋值价格
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(courseMarket.getCharge())) {
            dtoResult.setPrice(new BigDecimal(courseMarket.getPrice().toString()));
        }

        dtoResult.setCharge(courseMarket.getCharge());
        return dtoResult;
    }

    /**
     * 修改课程基础信息
     *
     * @param dto CourseBaseDTO
     * @return
     */
    @Override
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto) {
        // 1.判断关键数据
        // 课程的必要数据（在添加课程信息中判断）
        verifyCourseMsg(dto);
        // 课程的id值
        if (ObjectUtils.isEmpty(dto.getCourseBaseId())) {
            throw new RuntimeException("修改的课程id不能为空");
        }

        // 2.根据课程id查询课程基础信息
        CourseBase courseBase = this.getById(dto.getCourseBaseId());

        // 判断课程数据是否存在
        // 判断是否是同一家机构
        verifyPO(dto.getCompanyId(), courseBase);

        //判断课程是否是删除状态
        if (CommonEnum.USING_FLAG.getCodeInt() != courseBase.getStatus()) {
            throw new RuntimeException("课程已删除，无法修改");
        }

        // 判断课程的审核状态
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        // 3.修改数据
        // 课程的基础信息（course_base）
        CourseBase modifyPO = CourseBaseConvert.INSTANCE.dto2entity(dto);

        // po数据必须有id值
        boolean courseBaseResult = this.updateById(modifyPO);
        if (!courseBaseResult) {
            throw new RuntimeException("课程修改失败");
        }

        // 然后更新课程营销表（course_market）
        LambdaUpdateWrapper<CourseMarket> updateWrapper = new LambdaUpdateWrapper<>();
        // set方法填写的是set后的字段
        updateWrapper.set(CourseMarket::getCharge, dto.getCharge());

        // 如果课程为收费课程，需要对price进行修改操作
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())) {
            updateWrapper.set(CourseMarket::getPrice, dto.getPrice().floatValue());
        }

        //  eq方法填写的是where后的字段
        updateWrapper.eq(CourseMarket::getCourseId, dto.getCourseBaseId());

        boolean courseMarketResult = courseMarketService.update(updateWrapper);
        if (!courseMarketResult) {
            throw new RuntimeException("课程营销数据修改失败");
        }

        // 4.将修改后的结果转为dto数据返回
        CourseBase courseResult = this.getById(dto.getCourseBaseId());

        CourseBaseDTO courseBaseDTOResult = CourseBaseConvert.INSTANCE.entity2dto(courseResult);

        courseBaseDTOResult.setCharge(dto.getCharge());
        courseBaseDTOResult.setPrice(dto.getPrice());

        return courseBaseDTOResult;
    }

    private void verifyCourseMsg(CourseBaseDTO courseBaseDTO) {
        //对关键数据进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        if (ObjectUtils.isEmpty(courseBaseDTO)) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //对课程等级进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getGrade())) {
            ExceptionCast.cast(ContentErrorCode.E_120007);
        }
        //对大分类进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getMt())) {
            ExceptionCast.cast(ContentErrorCode.E_120002);
        }
        //对课程名称进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getName())) {
            ExceptionCast.cast(ContentErrorCode.E_120004);
        }
        //对小分类进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getSt())) {
            ExceptionCast.cast(ContentErrorCode.E_120003);
            throw new RuntimeException("小分类不能为空");
        }
        //对教学模式进行判断
        if (ObjectUtils.isEmpty(courseBaseDTO.getTeachmode())) {
            ExceptionCast.cast(ContentErrorCode.E_120006);
        }
    }

    private void verifyPO(Long companyId, CourseBase courseBase) {
        // 判断课程数据是否存在
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        // 判断是否是同一家机构
        if (!(ObjectUtils.nullSafeEquals(companyId, courseBase.getCompanyId()))) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
    }

    /**
     * 根据Id移除课程基础信息
     *
     * @param courseBaseId 课程id
     * @param companyId    机构id
     */
    @Override
    @Transactional
    public void removeCourseBaseById(Long courseBaseId, Long companyId) {
        //1.判断关键数据的合法性
        if (!ObjectUtil.isAllNotEmpty(courseBaseId, companyId)) {
            throw new RuntimeException("关键数据不能为空");
        }
        //2.根据Id获得课程基础信息并进行相应的判断
        //2.1 获得课程基础信息
        CourseBase courseBase = getById(courseBaseId);

        //2.2 判断数据是否为空
        if (ObjectUtils.isEmpty(courseBase))
            throw new RuntimeException("删除数据不存在");

        //2.3 判断修改的课程基础信息的公司Id和教师的公司Id是否一致
        if (!(ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)))
            throw new RuntimeException("无权限删除课程数据");

        //2.4 判断课程的审核状态
        String auditStatus = courseBase.getAuditStatus();

        if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            throw new RuntimeException("课程已发布或已审核");
        }
        //3.更新课程删除状态
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getStatus, CommonEnum.DELETE_FLAG.getCodeInt());
        updateWrapper.eq(CourseBase::getCompanyId, companyId);
        updateWrapper.eq(CourseBase::getId, courseBaseId);
        boolean removeResult = this.update(updateWrapper);
        if (!removeResult) {
            throw new RuntimeException("课程删除失败,课程id为:" + courseBaseId + "机构id为:" + companyId);
        }
    }

    /**
     * 教育机构提交课程基础信息
     *
     * @param courseBaseId 课程基础信息id
     * @param companyId    机构id
     */
    @Override
    @Transactional
    public void commitCourseBase(Long courseBaseId, Long companyId) {
        //查询课程id对应的课程信息
        CourseBase courseBase = this.getById(courseBaseId);
        //判断关键数据
        if (!ObjectUtil.isAllNotEmpty(courseBaseId, companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //判断关键数据
        verifyPO(companyId, courseBase);

        //判断课程是否是删除状态
        if (!CommonEnum.USING_FLAG.getCodeInt().equals(courseBase.getStatus())) {
            throw new RuntimeException("课程已删除，无法修改");
        }
        // 判断课程的审核状态
        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        //更新课程提交状态
        //1.设置更新条件
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId, courseBaseId);
        //2.提交课程基本信息,修改审核状态
        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }


    }


    /**
     * 审核课程基本信息-运营
     *
     * @param dto 课程基本信息
     *            1.判断关键数据:
     *            课程基础信息id
     *            课程审核状态
     *            2.判断课程数据
     *            判断课程是否存在
     */
    @Override
    public void approve(CourseBaseDTO dto) {
        //判断关键数据
        if (ObjectUtils.isEmpty(dto.getCourseBaseId()) || StringUtil.isBlank(dto.getAuditStatus())) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //判断课程数据
        CourseBase courseBase = this.getById(dto.getCourseBaseId());

        //判断课程是否存在
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        //判断课程是否被删除
        if (CommonEnum.DELETE_FLAG.getCodeInt().equals(courseBase.getStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }

        //判断课程审核状态:只有已经提交的状态才能被审核
        if (!(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(courseBase.getAuditStatus()))) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //修改课程审核状态
        //课程审核状态
        String auditStatus = dto.getAuditStatus();
        //课程审核意见
        String auditMind = dto.getAuditMind();
        //课程审核次数
        Integer auditNums = courseBase.getAuditNums();
        auditNums += 1;
        //审核修改时间
        LocalDateTime auditDate = LocalDateTime.now();

        //设置更新条件
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.set(CourseBase::getAuditStatus, auditStatus);
        updateWrapper.set(CourseBase::getAuditMind, auditMind);
        updateWrapper.set(CourseBase::getAuditNums, auditNums);
        updateWrapper.set(CourseBase::getAuditDate, auditDate);
        updateWrapper.set(CourseBase::getChangeDate, auditDate);
        updateWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        //更新课程审核状态
        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
    }

    /**
     * 课程信息预览
     *
     * @param courseBaseId 课程信息id
     * @param companyId    机构id
     * @return html内容
     * <p>
     * ===注意事项===
     * 业务方法返回的数据:
     * 课程预览的数据模型(dataMap)
     * <p>
     * ===业务分析===(需要开启事务)
     * 1.判断关键数据
     * courseBaseId,companyId
     * 2.判断业务数据
     * 根据id获得课程基本信息,判断其中的数据
     * 判断课程是否存在
     * 判断课程是否被删除
     * 判断课程审核状态(未提交,审核未通过才能预览)
     * 判断是否是一家教育机构
     * 3.获取课程营销
     * 4.获取课程计划数据
     * 5.获取教师信息
     * 6.获取课程类型的名称(完善数据)调用系统管理微服务,获取数据
     * 7.获取课程的教学模式
     * CourseModelEunm  获取所有的枚举类型  CourseModelEunm.values
     * <p>
     * 8.保存课程发布信息CoursePub数据
     * 1.查看是否有课程所对应的课程发布数据
     * 有数据
     * 修改
     * 无数据
     * 保存
     * <p>
     * 9.封装数据模型数据DataMap 并且返回
     */
    @Override
    @Transactional
    public Map<String, Object> preview(Long courseBaseId, Long companyId) {
        CoursePub coursePub = getCoursePub(courseBaseId, companyId, false);

        HashMap<String, Object> dataMap = generateDataMap(coursePub);

        return dataMap;
    }

    private HashMap<String, Object> generateDataMap(CoursePub coursePub) {
        //9.封装数据模型数据dataMap并返回

        HashMap<String, Object> dataMap = new HashMap<>();
        //1.课程发布
        dataMap.put("coursePub", coursePub);
        //2.课程营销
        String jsonMarket = coursePub.getMarket();
        CourseMarket courseMarket = JsonUtil.jsonToObject(jsonMarket, CourseMarket.class);
        dataMap.put("courseMarket", courseMarket);
        //3.课程计划
        String jsonTeachplan = coursePub.getTeachplan();
        TeachplanDTO teachplanNode = JsonUtil.jsonToObject(jsonTeachplan, TeachplanDTO.class);
        dataMap.put("teachplanNode", teachplanNode);

        //7.获取课程的教学模式
        dataMap.put("courseTeachModeEnums", CourseModeEnum.values());
        //设置课程等级
        dataMap.put("courseGradeEnums", CourseGradeEnum.values());
        //设置教师信息
        String teachers = coursePub.getTeachers();
        List<CourseTeacher> teacherList = JsonUtil.jsonToList(teachers, CourseTeacher.class);
        dataMap.put("courseTeachers", teacherList);


        return dataMap;
    }

    private CoursePub getCoursePub(Long courseBaseId, Long companyId, Boolean isPublish) {
        //1.判断关键数据
        //companyId是教育机构预览课程时的关键数据
        if (ObjectUtils.isEmpty(courseBaseId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.判断业务数据
        CourseBase courseBase = this.getById(courseBaseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        //判断课程是否被删除
        if (CommonEnum.DELETE_FLAG.getCodeInt().equals(courseBase.getStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
        //判断课程审核状态
        String auditStatus = courseBase.getAuditStatus();
        //机构id为空,运营平台
        if (ObjectUtils.isEmpty(companyId)) {
            if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                    CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)) {
                ExceptionCast.cast(ContentErrorCode.E_120015);
            }
            //不为空,教育机构
        } else {
            if (!isPublish) {
                if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus) ||
                        CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus) ||
                        CourseAuditEnum.AUDIT_UNLINE_STATUS.getCode().equals(auditStatus)) {
                    ExceptionCast.cast(ContentErrorCode.E_120015);
                }
            }

            //判断是否同属一家教育机构
            if (!ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)) {
                ExceptionCast.cast(CommonErrorCode.E_100108);
            }
        }

        //3.获取课程营销数据并判断
        LambdaQueryWrapper<CourseMarket> marketLambdaQueryWrapper = new LambdaQueryWrapper<>();
        marketLambdaQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);
        CourseMarket courseMarket = this.courseMarketService.getOne(marketLambdaQueryWrapper);
        if (ObjectUtils.isEmpty(courseMarket)) {
            ExceptionCast.cast(ContentErrorCode.E_120101);
        }

        //4.获取课程计划数据
        TeachplanDTO teachplanDTO = this.teachplanService.queryTreeNodesByCourseBaseId(courseBaseId, companyId);

        //5.获取教师信息
        List<CourseTeacherDTO> dtoList = this.courseTeacherService.queryTeacherList(courseBaseId);
        if (CollectionUtils.isEmpty(dtoList)) {
            ExceptionCast.cast(ContentErrorCode.E_1200503);
        }

        //6.获取课程类型的名称(完善数据),调用系统管理微服务,获取数据
        String mt = courseBase.getMt();
        String st = courseBase.getSt();
        RestResponse<CourseCategoryDTO> mtResponse = this.systemApiAgent.get(mt);
        RestResponse<CourseCategoryDTO> stResponse = this.systemApiAgent.get(st);
        if (!mtResponse.isSuccessful()) {
            ExceptionCast.castWithCodeAndDesc(mtResponse.getCode(), mtResponse.getMsg());
        }
        if (!stResponse.isSuccessful()) {
            ExceptionCast.castWithCodeAndDesc(stResponse.getCode(), stResponse.getMsg());
        }
        String mtName = mtResponse.getResult().getName();
        String stName = stResponse.getResult().getName();

        //8.保存课程发布信息CoursePub数据,并且判断

        CoursePub coursePub = CoursePubConvert.INSTANCE.courseBase2coursePub(courseBase);


        //设置营销信息
        coursePub.setMarket(JsonUtil.objectTojson(courseMarket));
        //设置课程计划信息
        coursePub.setTeachplan(JsonUtil.objectTojson(teachplanDTO));
        //设置教师信息
        coursePub.setTeachers(JsonUtil.listTojson(dtoList));

        //设置分类信息
        coursePub.setMtName(mtName);
        coursePub.setStName(stName);
        //设置状态
        coursePub.setStatus(teachplanDTO.getStatus());
        //设置收费规则
        coursePub.setCharge(courseMarket.getCharge());
        //设置原价和现价
        coursePub.setPrice(courseMarket.getPrice());
//        coursePub.setPriceOld(199F);目前不用设置
//          设置咨询qq
//        coursePub.setQq("936124096");

        //设置课程有效期
//        coursePub.setStartTime(null);
//        coursePub.setEndTime(null);
        //设置修改时间
        coursePub.setChangeDate(LocalDateTime.now());
        //设置是否最新课程
        //判断是修改还是新增
        LambdaQueryWrapper<CoursePub> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CoursePub::getCourseId, courseBaseId);
        CoursePub queryCoursePub = this.coursePubService.getOne(wrapper);
        if (ObjectUtils.isEmpty(queryCoursePub)) {
            //如果是新增就设置发布时间,并且设置最新课程
            coursePub.setCreateDate(LocalDateTime.now());
            coursePub.setIsLatest(1);
            //保证id为null
            coursePub.setId(null);
            boolean result = this.coursePubService.save(coursePub);
            if (!result) {
                ExceptionCast.cast(ContentErrorCode.E_120206);
            }

        } else {
            coursePub.setChangeDate(LocalDateTime.now());
            coursePub.setIsLatest(0);
            coursePub.setId(queryCoursePub.getId());
            boolean result = this.coursePubService.updateById(coursePub);
            if (!result) {
                ExceptionCast.cast(ContentErrorCode.E_120207);
            }
        }

        return coursePub;
    }

    /**
     * 课程发布
     *
     * @param courseBaseId 课程id
     * @param companyId    机构id
     * ========业务分析=======
     * 1.判断关键数据
     * courseBaseId,companyId
     * 2.判断业务数据
     * 判断课程基本信息是否存在
     * 判断课程是否删除
     * 判断课程状态
     * 判断是否同一家机构
     * 3.发送事务消息
     * 发送关键的数据courseBaseId
     */
    @Value("${course.publish.topic}")
    private String topic_name;

    @Override
    public void publish(Long courseBaseId, Long companyId) {
        //1.判断关键数据
        if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        //2.判断业务数据
        CourseBase courseBase = this.getById(courseBaseId);
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        //判断课程是否被删除
        if (CommonEnum.DELETE_FLAG.getCodeInt().equals(courseBase.getStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
        //判断课程审核状态
        if (!CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(courseBase.getAuditStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120201);
        }
        //判断是否同属一家教育机构
        if (!ObjectUtils.nullSafeEquals(courseBase.getCompanyId(), companyId)) {
            ExceptionCast.cast(CommonErrorCode.E_100108);
        }
        //3.发送事务消息
        Message<Long> message = MessageBuilder.withPayload(courseBaseId).build();

        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(topic_name, message, null);
        if (LocalTransactionState.COMMIT_MESSAGE != result.getLocalTransactionState()) {
            ExceptionCast.cast(ContentErrorCode.E_120202);
        }
    }

    /**
     * 执行本地事务保存CoursePub并更改课程审核状态
     *
     * @param courseBaseId 课程id
     *                     1.判断课程是否已经发布(幂等性:课程信息的审核状态是否发布)
     *                     如果已经发布,无需操作
     *                     如果未发布,进行课程发布
     *                     2.获取课程发布的最新数据并保存(修改或者新增)
     *                     3.修改课程审核状态
     */
    @Override
    public void saveCoursePubAndModifyAuditStatus(Long courseBaseId) {
        //1.判断课程是否已经发布
            CourseBase courseBase = this.getById(courseBaseId);
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(courseBase.getAuditStatus())) {
            ExceptionCast.cast(ContentErrorCode.E_120201);
        }
        //2.获取课程发布的最新数据并保存(修改或者新增)
        getCoursePub(courseBase.getId(), courseBase.getCompanyId(), true);

        //修改课程审核状态
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId, courseBaseId);

        boolean result = this.update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120208);
        }

    }
}
